package com.iotp.controller.admin.role;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iotp.controller.admin.base.BaseController;
import com.iotp.entity.authority.Authority;
import com.iotp.entity.base.DataMessage;
import com.iotp.entity.base.KKpager;
import com.iotp.entity.base.TreeData;
import com.iotp.entity.menu.Menu;
import com.iotp.entity.role.Role;
import com.iotp.entity.roleAuthorityRef.RoleAuthorityRef;
import com.iotp.entity.roleMenuRef.RoleMenuRef;
import com.iotp.service.authority.AuthorityService;
import com.iotp.service.menu.MenuService;
import com.iotp.service.role.RoleService;
import com.iotp.service.roleAuthorityRef.RoleAuthorityRefService;
import com.iotp.service.roleMenuRef.RoleMenuRefService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iotp.utils.common.WyConstant;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletOutputStream;
import java.io.*;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;


/**
 * 系统角色管理控制器
 * @author Assassin
 */
@Controller
@RequestMapping("/sys/role")
public class RoleController extends BaseController {
	
	@Autowired
	private RoleService roleService;// 系统角色业务接口
	@Autowired
	private MenuService menuService;// 系统菜单业务接口
	@Autowired
	private RoleMenuRefService roleMenuRefService;// 角色-菜单-关联业务接口;
	@Autowired
	private AuthorityService authorityService;// 系统权限业务接口
	@Autowired
	private RoleAuthorityRefService roleAuthorityRefService;// 角色-权限-关联业务接口
	
	/**
	 * 进入系统角色列表页面
	 * @return sys/role/list_role
	 */
	@GetMapping("/list")
	public String gotoListPage() {
		return "admin/sys/role/list_role";
	}
	
	/**
	 * 进入系统角色添加页面
	 * @return sys/role/add_role
	 */
	@GetMapping("/toAdd")
	public String gotoAddPage() {
		// 查询系统菜单信息
		List<Menu> menuList = this.menuService.queryList(null, null, null, null, null, 0,
				null, null, null, null, null, null, null, null, null, null,
				null, null);
		List<TreeData> menuTreeDataList = new ArrayList<TreeData>();
		menuTreeDataList.add(new TreeData("0", null, "菜单权限[选择角色所拥有的菜单权限]", false, true));
		for (Menu menu : menuList) {
			menuTreeDataList.add(new TreeData(menu.getMenuId().toString(), menu.getMenuPid().toString(), menu.getMenuName() + "[" + (menu.getMenuDesc() == null || "".equals(menu.getMenuDesc().trim()) ? "—"  : menu.getMenuDesc()) + "]", false, true));
		}
		request.setAttribute("menuTreeData", JSONArray.toJSONString(menuTreeDataList));
		// 查询系统权限信息
		List<Authority> authList = this.authorityService.queryList(null, null, null, null,
				null, null, 0, null, null, null, null, null,
				null, null, null, null, null);
		List<TreeData> authorityTreeDataList = new ArrayList<TreeData>();
		authorityTreeDataList.add(new TreeData("0", null, "操作权限[选择角色所拥有的操作权限]", false, true));
		for (Authority auth : authList) {
			authorityTreeDataList.add(new TreeData(auth.getAuthorityId().toString(), auth.getAuthorityPid().toString(), auth.getAuthorityName() + "[" + (auth.getAuthorityDesc() == null || "".equals(auth.getAuthorityDesc().trim()) ? "—"  : auth.getAuthorityDesc()) + "]", false, true));
		}
		request.setAttribute("authorityTreeData", JSONArray.toJSONString(authorityTreeDataList));
		return "admin/sys/role/add_role";
	}
	
	/**
	 * 进入系统角色编辑页面
	 * @param roleId 角色Id
	 * @return sys/role/edit_role
	 */
	@GetMapping("/toEdit")
	public String gotoEditPage(@RequestParam(required = true, value = "roleId") String roleId) {
		// 后台数据验证
		if(!this.validateStringProperty(roleId, 50, true)) {
			// TODO 错误页面
			return "redirect:/error";
		} 
		Role editRole = this.roleService.queryById(Long.parseLong(roleId));
		if(editRole == null) {
			return "redirect:/error";
		}
		// 查询菜单信息
		List<Menu> menuList = this.menuService.queryList(null, null, null, null, null, 0,
				null, null, null, null, null, null, null, null, null, null,
				null, null);
		List<RoleMenuRef> menuRefList = this.roleMenuRefService.queryList(Long.parseLong(roleId));
		List<TreeData> menuTreeDataList = new ArrayList<TreeData>();
		menuTreeDataList.add(new TreeData("0", null, "菜单权限[选择角色所拥有的菜单权限]", false, true));
		for (Menu menu : menuList) {
			boolean isChecked = false;
			for(RoleMenuRef ref : menuRefList) {
				if(menu.getMenuId().longValue() == ref.getMenuId().longValue()) {
					isChecked = true;
					break;
				}
			}
			menuTreeDataList.add(new TreeData(menu.getMenuId().toString(), menu.getMenuPid().toString(),
					menu.getMenuName() + "[" + (menu.getMenuDesc() == null || "".equals(menu.getMenuDesc().trim())
							? "—" : menu.getMenuDesc()) + "]",
					isChecked, true));
		}
		request.setAttribute("menuTreeData", JSONArray.toJSONString(menuTreeDataList));
		// 查询权限信息
		List<Authority> authList = this.authorityService.queryList(null, null, null, null,
				null, null, 0, null, null, null, null, null,
				null, null, null, null, null);
		List<RoleAuthorityRef> refList = this.roleAuthorityRefService.queryList(Long.parseLong(roleId));
		List<TreeData> treeDataList = new ArrayList<TreeData>();
		treeDataList.add(new TreeData("0", null, "操作权限[选择角色所拥有的操作权限]", false, true));
		for (Authority auth : authList) {
			boolean isChecked = false;
			for(RoleAuthorityRef ref : refList) {
				if(auth.getAuthorityId().longValue() == ref.getAuthorityId().longValue()) {
					isChecked = true;
					break;
				}
			}
			treeDataList.add(new TreeData(auth.getAuthorityId().toString(), auth.getAuthorityPid().toString(),
					auth.getAuthorityName() + "[" + (auth.getAuthorityDesc() == null || "".equals(auth.getAuthorityDesc().trim())
							? "—" : auth.getAuthorityDesc()) + "]",
					isChecked, true));
		}
		request.setAttribute("authorityTreeData", JSONArray.toJSONString(treeDataList));
		request.setAttribute("editRole", editRole);
		return "admin/sys/role/edit_role";
	}
	
	/**
	 * 加载系统角色表格数据
	 * @param pageNo 当前页码
	 * @param pageSize 每页记录数
	 * @param roleName 角色名称
	 * @param roleDesc 角色说明
	 * @return DataMessage
	 */
	@ResponseBody
	@PostMapping("/dataTable")
	public DataMessage selectTreeTable(
			@RequestParam(required = false, value = "pageNo") Integer pageNo,
			@RequestParam(required = false, value = "pageSize") Integer pageSize,
			@RequestParam(required = false, value = "roleName") String roleName,
			@RequestParam(required = false, value = "roleDesc") String roleDesc) {
		// 返回数据消息实体
		DataMessage dm = new DataMessage();
		PageHelper.startPage(getPageNo(pageNo), getPageSize(pageSize));
		PageHelper.orderBy("role_code");
		List<Role> roleList = this.roleService.queryList(null, null, getOrgType(), getOrgId(), null, 0, null, roleName,
				roleDesc, null, null);
		PageInfo<Role> pageInfo = new PageInfo<Role>(roleList);
		dm.setResult(WyConstant.RESULT_CODE_SUCCESS);
		dm.setData(roleList);
		KKpager pager = new KKpager(getPageNo(pageNo), pageInfo.getPages() , pageInfo.getTotal());
		dm.setMessage(JSONObject.toJSON(pager).toString());
		return dm;
	}
	
	/**
	 * 验证角色是否存在
	 * @param roleId 角色Id
	 * @param roleName 角色名称
	 * @param -validateType[roleName]
	 * @return DataMessage
	 */
	@ResponseBody
	@PostMapping("/validateIsRoleExist")
	public DataMessage validateIsRoleExist(
			@RequestParam(required = false, value = "roleId") String roleId,
			@RequestParam(required = false, value = "roleName") String roleName,
			@RequestParam(required = true, value = "validateType") String validateType) throws ParseException {
		// 返回数据消息实体
		DataMessage dm = new DataMessage();
		// 后台数据验证
		if(!this.validateStringProperty(validateType, 50, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("验证类型参数错误");
		} else if(!this.validateStringProperty(roleId, 50, false)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色标识参数错误");
		} else if(!this.validateStringProperty(roleName, 50, false)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色名称参数错误");
		} else {
			Long rid = null;
			if(roleId != null && !"".equals(roleId.trim())) {
				rid= Long.parseLong(roleId);
			}
			dm.setResult(WyConstant.RESULT_CODE_SUCCESS);
			List<Role> roleList = this.roleService.queryIsRoleExist(getOrgId(), rid, roleName);
			if(roleList == null || roleList.size() == 0) {
				dm.setData("0");
			} else {
				dm.setData("1");
			}
		}
		return dm;
	}
	
	/**
	 * 添加系统角色
	 * @param roleName 角色名称
	 * @param menuIds 菜单Ids
	 * @param authorityIds 权限Ids
	 * @param roleDesc 角色说明
	 * @return DataMessage
	 */
	@ResponseBody
	@PostMapping("/add")
	public DataMessage add(
			@RequestParam(required = true, value = "roleName") String roleName,
			@RequestParam(required = true, value = "menuIds") String menuIds,
			@RequestParam(required = true, value = "authorityIds") String authorityIds,
			@RequestParam(required = false, value = "roleDesc") String roleDesc) {
		// 返回数据消息实体
		DataMessage dm = new DataMessage();
		// 后台数据验证
		if(!this.validateStringProperty(roleName, 50, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色名称参数错误");
		} else if(!this.validateStringProperty(menuIds, 128, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("菜单权限参数错误");
		} else if(!this.validateStringProperty(authorityIds, 128, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("操作权限参数错误");
		} else if(!this.validateStringProperty(roleDesc, 255, false)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色说明参数错误");
		} else {
			boolean isExist = false;
			List<Role> roleList = this.roleService.queryIsRoleExist(getOrgId(), null, roleName);
			if(roleList != null && roleList.size() > 0) {
				dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
				dm.setMessage("角色名称已经存在");
				isExist = true;
			} 
			if(!isExist) {
				Long roleId = this.roleService.add(getOrgType(), getOrgId(), getOrgCode(), roleName, roleDesc, menuIds, authorityIds);
				dm.setResult(WyConstant.RESULT_CODE_SUCCESS);
				dm.setData(roleId);
				dm.setMessage("角色添加成功");
			}
		}
		return dm;
	}
	
	/**
	 * 编辑系统角色
	 * @param roleId 角色Id
     * @param roleName 角色名称
     * @param menuIds 菜单Ids
     * @param authorityIds 权限Ids
	 * @param roleDesc 角色说明
	 * @return DataMessage
	 */
	@ResponseBody
	@PostMapping("/edit")
	public DataMessage edit(
			@RequestParam(required = true, value = "roleId") String roleId,
			@RequestParam(required = true, value = "menuIds") String menuIds,
			@RequestParam(required = true, value = "authorityIds") String authorityIds,
			@RequestParam(required = false, value = "roleName") String roleName,
			@RequestParam(required = false, value = "roleDesc") String roleDesc) {
		// 返回数据消息实体
		DataMessage dm = new DataMessage();
		// 后台数据验证
		if(!this.validateStringProperty(roleId, 50, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色Id参数错误");
		} else if(!this.validateStringProperty(roleName, 50, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色名称参数错误");
		} else if(!this.validateStringProperty(menuIds, 128, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("菜单权限参数错误");
		} else if(!this.validateStringProperty(authorityIds, 128, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("操作权限参数错误");
		} else if(!this.validateStringProperty(roleDesc, 255, false)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色说明参数错误");
		} else {
			boolean isExist = false;
			List<Role> roleList = this.roleService.queryIsRoleExist(getOrgId(), Long.parseLong(roleId), roleName);
			if(roleList != null && roleList.size() > 0) {
				dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
				dm.setMessage("角色名称已经存在");
				isExist = true;
			} 
			if(!isExist) {
				this.roleService.edit(Long.parseLong(roleId), getOrgId(), null, null, null, roleName, roleDesc, menuIds, authorityIds);
				dm.setResult(WyConstant.RESULT_CODE_SUCCESS);
				dm.setMessage("角色编辑成功");
			}
		}
		return dm;
	}
	
	/**
	 * 删除系统角色
	 * @param roleId 角色Id
	 * @return DataMessage
	 */
	@ResponseBody
	@PostMapping("/delete")
	public DataMessage delete(@RequestParam(required = true, value = "roleId") String roleId) {
		// 返回数据消息实体
		DataMessage dm = new DataMessage();
		// 后台数据验证
		if(!this.validateStringProperty(roleId, 50, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色Id参数错误");
		} else {
			this.roleService.editIsDel(Long.parseLong(roleId), 1);
			dm.setResult(WyConstant.RESULT_CODE_SUCCESS);
			dm.setMessage("角色删除成功");
		}
		return dm;
	}
	
	/**
	 * 批量删除系统角色
	 * @param roleIds 角色Ids
	 * @return DataMessage
	 */
	@ResponseBody
	@PostMapping("/batchDelete")
	public DataMessage deleteBatch(@RequestParam(required = true, value = "roleIds") String roleIds) {
		// 返回数据消息实体
		DataMessage dm = new DataMessage();
		// 后台数据验证
		if(!this.validateStringProperty(roleIds, 128, true)) {
			dm.setResult(WyConstant.RESULT_CODE_PARAMETER_ERROR);
			dm.setMessage("角色Ids参数错误");
		} else {
			String[] roleIdsArr = roleIds.split(",");
			for(String roleId : roleIdsArr) {
				this.roleService.editIsDel(Long.parseLong(roleId), 1);
			}
			dm.setResult(WyConstant.RESULT_CODE_SUCCESS);
			dm.setMessage("角色删除成功");
		}
		return dm;
	}
	
	/**
	 * 导出数据到Excel
	 * @param roleName 角色名称
	 * @param roleDesc 角色说明
	 * @return Excel File
	 * @throws Exception
	 */
	@PostMapping("/export")
    public ModelAndView exportExcel(
    		@RequestParam(required = false, value = "roleName") String roleName,
			@RequestParam(required = false, value = "roleDesc") String roleDesc) throws Exception {
        Workbook wb = new HSSFWorkbook();
        Sheet sheet = wb.createSheet("系统角色信息");
        // 手动设置列宽。第一个参数表示要为第几列设；，第二个参数表示列的宽度，n为列高的像素数。
        sheet.setColumnWidth((short) 0, (short) (15.7 * 150));
        sheet.setColumnWidth((short) 1, (short) (25.7 * 150));
        sheet.setColumnWidth((short) 2, (short) (35.7 * 150));
        sheet.setColumnWidth((short) 3, (short) (35.7 * 150));
        sheet.setColumnWidth((short) 4, (short) (35.7 * 150));
        sheet.setColumnWidth((short) 5, (short) (35.7 * 150));
        sheet.setColumnWidth((short) 6, (short) (35.7 * 150));
        sheet.setColumnWidth((short) 7, (short) (35.7 * 150));
        sheet.setColumnWidth((short) 8, (short) (35.7 * 150));
        // 创建第一行
        Row row = sheet.createRow((short) 0);
        // 创建两种单元格格式
        CellStyle cs = wb.createCellStyle();
        CellStyle cs2 = wb.createCellStyle();
        
        // 创建两种字体
        Font f = wb.createFont();
        Font f2 = wb.createFont();
        
        // 创建第一种字体样式
        f.setFontHeightInPoints((short) 12);
        f.setColor(IndexedColors.BLACK.getIndex());
        f.setBoldweight(Font.BOLDWEIGHT_BOLD);
        // 创建第二种字体样式
        f2.setFontHeightInPoints((short) 11);
        f2.setColor(IndexedColors.BLACK.getIndex());
        f2.setBoldweight(Font.BOLDWEIGHT_NORMAL);
        
        // 设置第一种单元格的样式
        cs.setFont(f);
        cs.setBorderLeft(CellStyle.BORDER_THIN);
        cs.setBorderRight(CellStyle.BORDER_THIN);
        cs.setBorderTop(CellStyle.BORDER_THIN);
        cs.setBorderBottom(CellStyle.BORDER_THIN);
        cs.setAlignment(HSSFCellStyle.ALIGN_LEFT);
        
        // 设置第二种单元格的样式
        cs2.setFont(f2);
        cs2.setBorderLeft(CellStyle.BORDER_THIN);
        cs2.setBorderRight(CellStyle.BORDER_THIN);
        cs2.setBorderTop(CellStyle.BORDER_THIN);
        cs2.setBorderBottom(CellStyle.BORDER_THIN);
        cs2.setAlignment(HSSFCellStyle.ALIGN_LEFT);
        
        // 创建列（每行里的单元格）
        Cell cell = row.createCell(0);
        cell.setCellValue("序号");
        cell.setCellStyle(cs);
        
        cell = row.createCell(1);
        cell.setCellValue("角色编码");
        cell.setCellStyle(cs);
        
        cell = row.createCell(2);
        cell.setCellValue("角色名称");
        cell.setCellStyle(cs);
        
        cell = row.createCell(3);
        cell.setCellValue("角色说明");
        cell.setCellStyle(cs);
        
        PageHelper.orderBy("role_code");
		List<Role> roleList = this.roleService.queryList(null, null, getOrgType(), getOrgId(), null, 0, null, roleName,
				roleDesc, null, null);
    	for(int i = 0; i < roleList.size(); i++) {
    		Role role = roleList.get(i);
    		row = sheet.createRow(i + 1);
    		cell = row.createCell(0);
    		cell.setCellValue(i + 1);
    		cell.setCellStyle(cs2);
    		  
    		cell = row.createCell(1);
    		cell.setCellValue(role.getRoleCode());
    		cell.setCellStyle(cs2);
    		  
    		cell = row.createCell(2);
    		cell.setCellValue(role.getRoleName());
    		cell.setCellStyle(cs2);
    		  
    		cell = row.createCell(3);
    		cell.setCellValue((role.getRoleDesc() == null || "".equals(role.getRoleDesc().trim())) ? "—" : role.getRoleDesc());
    		cell.setCellStyle(cs2);
    	}
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            wb.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] content = os.toByteArray();
        InputStream is = new ByteArrayInputStream(content);
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(("系统角色信息" + ".xls").getBytes(), "ISO-8859-1"));
        ServletOutputStream out = response.getOutputStream();
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(out);
            byte[] buff = new byte[2048];
            int bytesRead;
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
        } catch (final IOException e) {
            throw e;
        } finally {
            if (bis != null)
                bis.close();
            if (bos != null)
                bos.close();
        }
        return null;
	}
	
}